﻿/*
 * @Autor: PK
 * @Date: 2021/12/18 12:31:SS
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ShkSimulation.core.dao.output;
using ShkSimulation.core.dao.output.result;
using ShkSimulation.core.dao.statistic.feature;
using ShkSimulation.desktop.component.tools;
using ShkSimulation.carsharing.impl;

namespace ShkSimulation.desktop.component {

	public sealed class WinformConsoleTextBox : TextBox, ResultShower, ResetSimulation{

		private SimulationApplication application;

		private Timer timer;
		
		public WinformConsoleTextBox() {
			this.ContextMenuStrip = CreateMenuStrip();
			this.TextChanged += ConsoleTextBox_TextChanged;
			timer = new Timer();
			timer.Interval = 300;
			timer.Tick += InternalWrite;
			timer.Enabled = true;
			WinformConsoleTextWriter.Instance.OutputDataReceived += ProcessOnOutputDataReceived;
		}
		
		private StringBuilder builder = new StringBuilder();

		public void SetSimulationApplication(SimulationApplication app) {
			this.application = app;
			application.OnProcessInfoAdd += WriteLine;
		}

		private void ProcessOnOutputDataReceived(char c) {
			builder.Append(c);
		}

		private void InternalWrite(object sender, EventArgs e) {
			AppendConsole(builder.ToString());
			builder.Clear();
			void AppendConsole(string data) {
				if (!string.IsNullOrEmpty(data)) {
					BeginInvoke(new Action(() => {
						this.AppendText(data);
					}));
				}
			}
		}
		
		public void WriteLine(string data) {
			builder.AppendLine(data);
		}
		
		public void WriteLine(params string[] data) {
			if (data == null) {
				builder.AppendLine("null");
				return;
			}
			foreach (string line in data) {
				builder.AppendLine(line);
			}
		}

		public void WriteLine() {
			builder.AppendLine();
		}

		public void Show(Result result) {
			List<string> lines = new List<string>();
			lines.Add("Key:" + result.Uniquekey);
			lines.Add("Data:");
			var data = result.TakeOutputData();
			foreach (var (collectionUniqueKey, collectionReportData) in data.Data) {
				foreach ((VariableAndHourStatisticKey key, StatisticInfo value) in collectionReportData) {
					string temp = $"{collectionUniqueKey}-{key}";
					foreach (var dataPair in value) {
						lines.Add($"{temp}:{dataPair}");
					}
				}
			}
			WriteLine(lines.ToArray());
		}

		private ContextMenuStrip CreateMenuStrip() {
			ContextMenuStrip menuStrip = new ContextMenuStrip();
			menuStrip.Items.AddRange(CreateMenuItems());
			menuStrip.Name = "ConsoleTextMenuStrip";
			return menuStrip;
			
			ToolStripItem[] CreateMenuItems() {
				ToolStripItem clear = new ToolStripMenuItem();
				clear.Name = "ClearConsoleTextMenuItem";
				clear.Text = "清空";
				clear.Click += ClearItemClick;
				void ClearItemClick(object sender, EventArgs e) {
					this.Invoke(new Action(() => { this.Text = ""; }));
				}
				return new []{ clear };
			}
		}

		private void ConsoleTextBox_TextChanged(object sender, EventArgs e) {
			List<string> newLines = Lines.TakeLast(500 - Lines.Length).ToList();
			Lines = newLines.ToArray();
			if (this.TextLength <= 1) {
				return;
			}
			this.Focus();
			this.Select(this.TextLength - 1, 0);
			this.ScrollToCaret();
		}

		public void Reset() {
			this.application = null;
		}

	}
}